#include "packetContents.h"
#include <netinet/in.h>

/* msgparser takes in the array called packetbytes that has been received from
 the server and a pointer to a struct. The purpose of the function is to strip the
 array and assign appropriate values to the contents of the struct
 Assumptions: packetbytes is an array with indexes 0 - 9 (80 bits)
              length is a field in the struct */

/* content[0] = version (fixed at IPV4)
   content[1] = upper bits of packet length
   content[2] = lower bits of packet length
   content[3] = Msg type   * MOST IMPORTANT *
   content[4] onwards consists of the payload */

// HELPER FUNCTIONS

void set_victim_name(char packetbytes[], packetContents* content, int min, int max) {
    int i = 0;
    int j;
    for (j = min; j < max; j++) {
        content->victimName[i] = packetbytes[j];
        i++;
    }
    content->victimName[EE122_MAX_NAME_LENGTH] = 0;
}

void set_attacker_name(char packetbytes[], packetContents* content, int min, int max) {
    int i = 0;
    int j;
    for (j = min; j < max; j++) {
        content->attackerName[i] = packetbytes[j];
        i++;
    }
    content->attackerName[EE122_MAX_NAME_LENGTH] = 0;
}

long get_hp(char packetbytes[], int x) {
    long hp = 0;

    hp = packetbytes[x] << 24;
    hp |= packetbytes[x + 1] << 16;
    hp |= packetbytes[x + 2] << 8;
    hp |= packetbytes[x + 3];
    return hp;
}

long get_exp(char packetbytes[], int x) {
    long exp = 0;

    exp = packetbytes[x] << 24;
    exp |= packetbytes[x + 1] << 16;
    exp |= packetbytes[x + 2] << 8;
    exp |= packetbytes[x + 3];
    return exp;
}

void msgparser(char packetbytes[], packetContents* content) {
    // set the length within the struct to obtained length
    content->length = (packetbytes[1] << 16) | packetbytes[2];

    // Set message type
    content->messageType = packetbytes[3];

    switch (content->messageType) {
        case LOGIN_REPLY:
        {
            // Obtain error code
            content->errorCode = packetbytes[4];

            // Get Player HP
            content->hp = get_hp(packetbytes, 5);

            // Get Player EXP
            content->exp = get_exp(packetbytes, 9);

            // Extract the X coordinate from the packet
            content->xLoc = packetbytes[13];

            // Extract the Y coordinate from the packet
            content->yLoc = packetbytes[14];

            break;
        }

        case MOVE_NOTIFY:
        {

            set_victim_name(packetbytes, content, 4, 14);

            // Getting the X & Y Coordinates
            content->xLoc = packetbytes[14];
            content->yLoc = packetbytes[15];

            // Get Player HP
            content->hp = get_hp(packetbytes, 16);

            // Get Player EXP
            content->exp = get_hp(packetbytes, 20);

            break;
        }

        case ATTACK_NOTIFY:
        {

            // Get the attacker's name
            set_attacker_name(packetbytes, content, 4, 14);

            // Get the victim's name
            set_victim_name(packetbytes, content, 14, 24);

            content->damage = packetbytes[24];

            // Get Player HP
            content->hp = get_hp(packetbytes, 25);

            break;
        }

        case SPEAK_NOTIFY:
        {
            set_victim_name(packetbytes, content, 4, 14);

            int k = (content->length) - 14;
            int j;
            for (j = 0; j < k; j++)
                content->message[j] = packetbytes[j + 14];

            content->message[EE122_MAX_MSG_LENGTH] = 0;
            break;
        }

        case LOGOUT_NOTIFY:
        {
            set_victim_name(packetbytes, content, 4, 14);

            break;
        }


        case INVALID_STATE: content->errorCode = packetbytes[4];

    }
}
